<!-- eslint-disable vue/no-mutating-props -->
<script setup lang="ts">
import {
  DynamicFormItem,
  DynamicFormItemSubset,
  type FormConfigModel,
  type FormConfigElement
} from '@/DynamicForm'
import {
  NForm,
  NScrollbar,
  useMessage,
  type FormInst,
  NDataTable,
  NButton,
  type DataTableColumns,
  NModal
} from 'naive-ui'
import { sendRequest } from '@/utils/api'
import { ref, watch, h } from 'vue'
import VDialogContent from '@/views/OA/Common/DialogContent.vue'

type Data = Record<string, any>
type Vars = Record<string, any>
export interface DynamicFormComponentInst {
  formInst: FormInst | null
}

const props = withDefaults(
  defineProps<{
    data?: Data
    disabled?: boolean
    onlyTable?: boolean
    createVars?(e: FormConfigElement): Vars
    isCB?: boolean
    itemTypeCode?: string
    disabledKeys?: string[]
  }>(),
  {
    data: () => ({} as Data),
    disabled: false,
    onlyTable: false,
    createVars: () => () => ({} as Vars),
    isCB: false,
    disabledKeys: () => []
  }
)

const handleAddSubItem = (k: string) => {
  const subItems = props.data[k] || []
  subItems.push({
    flag: 2
  })
  console.log('subItems', k, subItems)
  props.data[k] = subItems
}

const deleteModalVisible = ref(false)
let deleteFunc: any
const handleDeleteSubItem = (k: string, i: number) => {
  deleteFunc = () => {
    const subItems = props.data[k]

    if (subItems) {
      subItems.splice(i, 1)
      props.data[k] = subItems
    }

    handleDeleteModalClose()
  }
  deleteModalVisible.value = true
}
const handleDeleteModalClose = () => {
  deleteModalVisible.value = false
  deleteFunc = null
}

const message = useMessage()
const formConfigModel = ref<FormConfigModel[]>([])
const configModelLoading = ref(false)
const fetchJsonUrlLoading = ref(false)
const formInst = ref<FormInst | null>(null)

const createTableData = (key: string) => {
  return props.data[key] || []
}

const createDataTableColumns = (
  key: string,
  func: any,
  elements: FormConfigElement[] = []
): DataTableColumns<any> => {
  const columns: DataTableColumns<any> = elements.map((e, i) => {
    const rowKey = e.formItemProps?.path || i
    return {
      title: () => {
        let isRequired = false
        const rules = e.formItemProps?.rule
        if (rules && !Array.isArray(rules)) {
          isRequired = rules.required || false
        } else if (Array.isArray(rules)) {
          isRequired = rules.some((r) => r.required || false)
        }

        if (isRequired) {
          return h('span', null, [e.formItemProps?.label, h('span', { style: 'color: red' }, '*')])
        }

        return e.formItemProps?.label
      },
      key: rowKey,
      align: 'center',
      cellProps: () => ({
        style: 'vertical-align: top'
      }),
      render(row, ri) {
        const isDisableEdit = row.flag === 0

        return h(DynamicFormItem, {
          vars: { formData: props.data },
          style: 'flex: 1',
          config: func(key, ri)[i] as FormConfigElement,
          showLabel: false,
          disabled: isDisableEdit || props.disabledKeys.includes(String(rowKey))
        })
      }
    }
  })

  columns.push({
    title: '操作',
    key: 'actions',
    align: 'center',
    width: 120,
    cellProps: () => ({
      style: 'vertical-align: top'
    }),
    render(row, i) {
      if (props.disabled) return null

      const { flag } = row
      const isDisableDelete = flag === 0 || flag === 1
      if (isDisableDelete) return null

      return h(
        NButton,
        {
          quaternary: true,
          type: 'error',
          size: 'small',
          onClick: () => handleDeleteSubItem(key, i)
        },
        { default: () => '删除' }
      )
    }
  })

  return columns
}

const handleDeleteDiff = () => {
  const dataKeys = Object.keys(props.data)
  const modelKeys = formConfigModel.value.reduce<string[]>(
    // @ts-ignore
    (acc, cur) => acc.concat(cur.elements.map((e) => e.formItemProps?.path)),
    []
  )
  const diffKeys = dataKeys.filter((k) => !modelKeys.includes(k))
  diffKeys.forEach((k) => delete props.data[k])
}

defineExpose({
  formInst
})

const handleVersionTypeChange = async () => {
  fetchJsonUrlLoading.value = true
  try {
    const [error, res] = await sendRequest({
      module: 'json',
      api: 'selectJsonUrlByCode',
      override: {
        params: {
          code: props.isCB ? props?.itemTypeCode : props.data.BMCOM003,
          cbFlag: props.isCB ? 1 : 0 //初编
        }
      }
    })
    if (error) throw error
    if (res.code !== 0) throw new Error(res.msg)
    if (!res.data) return message.warning('暂无配置！')
    handleQueryFormConfigModel(res.data)
  } catch (error) {
    if (error instanceof Error) message.error(error.message)
    console.error(error)
  } finally {
    fetchJsonUrlLoading.value = false
  }
}
if (!props.isCB) {
  watch(
    () => props.data.BMCOM003,
    () => handleVersionTypeChange(),
    { immediate: true }
  )
}

const handleQueryFormConfigModel = async (url: string) => {
  configModelLoading.value = true

  try {
    const res = await fetch(url)
    if (!res.ok) throw new Error('Network response was not ok.')
    formConfigModel.value = await res.json()
    console.log(handleDeleteDiff)

    formInst.value?.restoreValidation()
  } catch (error) {
    if (error instanceof Error) message.error(error.message)
    console.error(error)
  } finally {
    configModelLoading.value = false
  }
}

const elementStyle = (e: FormConfigModel) => {
  const style = {
    flex: '1'
  } as any
  if (e.elements.length === 1) style.gridColumn = '1 / span 2'

  return style
}
handleVersionTypeChange()
</script>

<template>
  <DetailFormProvider>
    <div class="dynamic-form">
      <NScrollbar style="max-height: 100%">
        <NForm
          ref="formInst"
          :model="data"
          label-placement="left"
          require-mark-placement="left"
          class="dynamic-form__content"
          :disabled="disabled"
          label-width="100"
        >
          <div
            v-for="(e, i) in formConfigModel"
            :key="i"
            class="form-group"
          >
            <slot
              name="title"
              :config="e"
            >
              <div
                v-if="e.title"
                class="form-group__title"
              >
                {{ e.title }}
              </div>
            </slot>

            <div class="form-group__items">
              <template v-for="(c, ci) in e.elements">
                <slot
                  name="control"
                  :config="c"
                >
                  <DynamicFormItem
                    flex="1"
                    :key="c.formItemProps?.path || ci"
                    :config="c"
                    :data-value="c.formItemProps?.path ? c.formItemProps.path in data : null"
                    :style="elementStyle(e)"
                    :vars="createVars(c)"
                    label-suffix="："
                    :disabled="
                      onlyTable ||
                      Boolean(
                        c.formItemProps?.path &&
                          disabledKeys.includes(c.formItemProps.path) &&
                          props.data?.['BMCOM003']?.indexOf('T002') != -1
                      )
                    "
                  />
                </slot>
              </template>
            </div>
            <template v-if="e.subset">
              <DynamicFormItemSubset
                :subset="e.subset"
                :data="data"
                @add:subItem="handleAddSubItem"
                @delete:subItem="handleDeleteSubItem"
                :disabled="disabled"
              >
                <template #default="{ elements, key, subItemConfigs }">
                  <NDataTable
                    :bordered="false"
                    size="small"
                    :columns="createDataTableColumns(key, subItemConfigs, elements)"
                    :data="createTableData(key)"
                  />
                </template>
              </DynamicFormItemSubset>
            </template>
          </div>

          <NModal
            :auto-focus="false"
            v-model:show="deleteModalVisible"
          >
            <VDialogContent
              @close="handleDeleteModalClose"
              @submit="deleteFunc && deleteFunc()"
              title="删除提示"
            >
              <div style="width: 350rem; height: 100rem; text-align: center; line-height: 100rem">
                您确定要删除吗？
              </div>
            </VDialogContent>
          </NModal>
        </NForm>
      </NScrollbar>
    </div>
  </DetailFormProvider>
</template>

<style scoped>
:deep(.n-scrollbar-container) {
  min-height: 100%;
}
:deep(.n-scrollbar-content) {
  height: 100%;
}

.dynamic-form__content {
  height: 100%;
  background-color: #e1e1e1;
}

.form-group__title {
  font-size: 14px;
  font-weight: 600;
  color: #333333;
  margin-bottom: 1em;
}

.form-group__items {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0 10px;
}
</style>
